package com.demo.java.netty.pipeline;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * 1. handler添加顺序:
 * ```
 * ch.pipeline().addLast(new InboundHandler1());
 * ch.pipeline().addLast(new InboundHandler2());
 * ch.pipeline().addLast(new OutboundHandler1());
 * ch.pipeline().addLast(new OutboundHandler2());
 * ```
 * 链表顺序为: head -> inbound1 -> inbound2 -> outbound1 -> outbound2 -> tail
 *
 * inbound2中执行ctx.pipeline().writeAndFlush或ctx.channel().writeAndFlush, netty从tail向前查找outbound.
 * 读顺序为: inbound1 -> inbound2
 * 写顺序为: outbound2 -> outbound1
 *
 * inbound2中执行ctx.writeAndFlush，netty从inbound2向前查找outbound.
 * 读顺序为: inbound1 -> inbound2
 * 写顺序为: 向前找不到outbound，所以不执行outbound
 *
 * 2. handler添加顺序:
 * ```
 * ch.pipeline().addLast(new OutboundHandler1());
 * ch.pipeline().addLast(new OutboundHandler2());
 * ch.pipeline().addLast(new InboundHandler1());
 * ch.pipeline().addLast(new InboundHandler2());
 * ```
 * 链表顺序为: head -> outbound1 -> outbound2 -> inbound1 -> inbound2 -> tail
 *
 * inbound2中执行ctx.pipeline().writeAndFlush或ctx.channel().writeAndFlush, netty从tail向前查找outbound.
 * 顺序为: inbound1 -> inbound2 -> outbound2 -> outbound1
 *
 * inbound2中执行ctx.writeAndFlush，netty从inbound2向前查找outbound.
 * 顺序为: inbound1 -> inbound2 -> outbound2 -> outbound1
 *
 * 结论：InboundHandler是通过fire事件决定是否要执行下一个InboundHandler，如果哪个InboundHandler没有调用fire事件，那么往后的Pipeline就断掉了。
 */
public class EchoServer {

    public static void main(String[] args) throws Exception {
        final ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(new NioEventLoopGroup(), new NioEventLoopGroup())
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline()
                                .addLast(new InboundHandler1())
                                .addLast(new InboundHandler2())
                                .addLast(new OutboundHandler1())
                                .addLast(new OutboundHandler2())

                                /*.addLast(new OutboundHandler1())
                                .addLast(new OutboundHandler2())
                                .addLast(new InboundHandler1())
                                .addLast(new InboundHandler2())*/;
                    }
                });
        bootstrap.bind(8080).sync().channel().closeFuture().sync();
    }
}
